package com.chhuang.ewcrm.comm;

import gnu.io.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.TooManyListenersException;

/**
 * 串口启动监听和发送信息类
 */
public class CommStartListener implements SerialPortEventListener {
    private final Logger logger = LoggerFactory.getLogger(CommStartListener.class);

    private final CommCallBack commCallBack;
    private SerialPort serialPort;
    private final BufferedInputStream bufferInput;

    public CommStartListener(Serial serial, CommCallBack commCallBack) throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, IOException, TooManyListenersException {
        this.commCallBack = commCallBack;

        //获取通信端口标识符
        CommPortIdentifier comm = Serial.getCommPortIdentifierByName(serial.getCommName());
        //打开串口
        serialPort = (SerialPort) comm.open(serial.getCommName(),2000);
        //如果串口不为空的话 则监听获取信息 否则报错
        if (serialPort != null) {
            //设置串口的参数 波特率 数据位 停止位 奇偶效验
            serialPort.setSerialPortParams(serial.getBaudRate(), serial.getDataBits(), serial.getStopBits(), serial.getParity());
            //获取输入流
            bufferInput = new BufferedInputStream(serialPort.getInputStream());
            //添加监听
            serialPort.addEventListener(this);
            serialPort.notifyOnDataAvailable(true);
        }else {
            throw new RuntimeException("串口获取失败-serialPort为null");
        }

    }

    @Override
    public void serialEvent(SerialPortEvent serialPortEvent) {
        String hexStr = null;
        //判断数据类型
        switch (serialPortEvent.getEventType()) {
            //通讯中断 Break Interrupt
            case SerialPortEvent.BI:
                logger.debug("BI:通讯中断 Break Interrupt");
                break;
            //溢位错误 Overrun Error
            case SerialPortEvent.OE:
                logger.debug("OE:溢位错误 Overrun Error");
                break;
            //传帧错误 Framing Error
            case SerialPortEvent.FE:
                logger.debug("FE:传帧错误 Framing Error");
                break;
            //效验错误 Parity Error
            case SerialPortEvent.PE:
                logger.debug("PE:效验错误 Parity Error");
                break;
            //载波检测 Carrier Detect
            case SerialPortEvent.CD:
                logger.debug("CD:载波检测 Carrier Detect");
                break;
            //清除发送 Clear To Send
            case SerialPortEvent.CTS:
                logger.debug("CTS:清除发送 Clear To Send");
                break;
            //数据设备就绪 Data Set Ready
            case SerialPortEvent.DSR:
                logger.debug("DSR:数据设备就绪 Data Set Ready");
                break;
            //响铃指示 Ring Indicator
            case SerialPortEvent.RI:
                logger.debug("RI:响铃指示 Ring Indicator");
                break;
            //输出缓冲区清空 Output Buffer Empty
            case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
                logger.debug("output:输出缓冲区清空 Output Buffer Empty");
                break;
            //端口有可用数据 Data Available
            case SerialPortEvent.DATA_AVAILABLE:
                //读取数据
                try {
                    byte[] bytes = null;
                    byte[] tempBytes = new byte[1024];
                    int len;
                    while (-1 != (len = bufferInput.read(tempBytes))) {
                        //将数据写入bytes中 并更改bytes的长度
                        if (bytes != null) {
                            byte[] b = bytes;
                            bytes = new byte[bytes.length + len];
                            for (int i = 0; i < bytes.length; i++) {
                                if (i < len) {
                                    bytes[i] = b[i];
                                } else {
                                    bytes[i] = tempBytes[i];
                                }
                            }
                        } else {
                            bytes = new byte[len];
                            if (bytes.length >= 0) System.arraycopy(tempBytes, 0, bytes, 0, bytes.length);
                        }
                    }
                    assert bytes != null;
                    hexStr = Protocal.switchByteToHexadecimal(bytes);
                    //输出数据
//                    System.out.println("字符串形式:" + new String(bytes));
//                    System.out.println("16进制形式:" + hexStr);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + serialPortEvent.getEventType());
        }

        commCallBack.doSuccess(hexStr);
    }

    /**
     * 发送信息
     * @param hexStr 十六进制字符串
     */
    public void send(String hexStr){
        if(serialPort!=null){
            OutputStream output;
            try {
                output = serialPort.getOutputStream();
                Serial.sendData(output, Protocal.switchStringToHexadecimal(hexStr));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭串口
     */
    public void close(){
        if(serialPort!=null){
            serialPort.close();
            serialPort=null;
        }
    }
}
